var crypto = require('../utils/crypto');
var logger = require('../utils/log');
var redis = require("../utils/redis");
var constant = require('../utils/constant');

var roomMgr = require('./roommgr');
var gameMgr = require('./gamemgr_bbmj');

var io = null;
var socketIDs = {};

exports.start = function(config){

    io = require('socket.io')(config.SOCKET_PORT, {path: '/socket.io/1'});

	io.sockets.on('connection',function(socket){

		socket.on('login',function(data){
			//绑定socket
            if(socket.userId != null) return;

            data = JSON.parse(data);
            var userId = data.userId;
            var roomNo = data.roomNo;
            var sign = data.sign;

            if (userId == null || roomNo == null || sign == null) {
                logger.error("socket params error");
                socket.emit('login_result_notify',{code:1,msg:"params error"});
                return;
            }

            var md5 = crypto.md5(roomNo + String(userId) + config.ROOM_PRI_KEY);
            if (md5 != sign) {
                logger.error("socket sign error");
                socket.emit('login_result_notify',{code:2,msg:"sign error"});
                return;
            }

            socket.userId = userId;
            socketIDs[userId] = socket.id;
            //加入房间
            socket.join(roomNo);

            var state = gameMgr.gameState(roomNo);
            var room = roomMgr.getRoomByRoomNo(roomNo);
            if (room == null) return;

            //如果是断线重连
            var userInfo = room.userInfos[userId];
            if (userInfo) {//座位信息存在
                socket.to(roomNo).emit('game_whoOnline_notify', userId);

                var reconnect = data.flag; //断线重连标识
                if (reconnect != 1) { //杀掉程序 重新连接
                    socket.emit('login_result_notify',{code:0, state:state, userInfos:room.userInfos});
                }
            } else { //游戏还没开始 返回座位信息
                socket.emit('login_result_notify',{code:0, state:state, userInfos:room.userInfos});
            }
		});

        //断开连接
        socket.on('disconnect',function(data){
            //移除socket
            var userId = socket.userId;
            logger.error('socket disconnect', userId);
            if (userId == null) return;

            //谁socket断开 表明离线
            var room = roomMgr.getRoomByUserId(userId);
            if (room != null) {
                socket.to(room.roomNo).emit('game_whoOffline_notify',userId);

                socket.leave(room.roomNo, null);
            }
            socket.userId = null;
            delete socketIDs[userId];
            socket.disconnect();
        });

        //连接错误
        socket.on('error', function(data){
            logger.error('socket error', data);
        });

        //坐下
        socket.on('sit', function (data) {
            var userId = socket.userId;
            if (userId == null || data == null) return;
            data = JSON.parse(data);
            var roomNo = data.roomNo;
            var account = data.account;
            redis.getUserInfo(account, function (userInfo) {
                logger.debug('game_whoSit_notify', userInfo.name);
                userInfo.ip = socket.handshake.address;
                roomMgr.sitRoom(userId, roomNo, userInfo);
                gameMgr.setupGame(userId, roomNo);
                io.to(roomNo).emit('game_whoSit_notify', {userId:userId,userInfo:userInfo});
            });
        });

        //如果准备人数完成 开始游戏
        socket.on('begin', function(data){
            var userId = socket.userId;
            if (userId == null || data == null) return;

            var roomNo = data;
            //先通知 再开局
            io.to(roomNo).emit('game_begin_notify', null);
            gameMgr.beginGame(userId, roomNo);
        });

        //如果准备人数完成 开始游戏
        socket.on('ready', function(data){
            var userId = socket.userId;
            if (userId == null || data == null) return;

            var roomNo = data;
            gameMgr.ready(userId, roomNo);
            io.to(roomNo).emit('game_whoReady_notify', userId);
        });

        //离开房间
        socket.on('offline', function (data) {
            var userId = socket.userId;
            logger.error('socket offline', userId);
            if (userId == null || data == null) return;

            var index = data;
            var room = roomMgr.getRoomByUserId(userId);
            if (room != null) {
                var roomNo = room.roomNo;
                roomMgr.offlineRoom(userId, roomNo, index);//退出房间
                socket.to(roomNo).emit('game_whoOffline_notify',userId);

                socket.leave(roomNo, null);
            }
            socket.userId = null;
            delete socketIDs[userId];
            socket.disconnect();
        });

        //回到房间
        // socket.on('online', function (data) {
        //     var userId = socket.userId;
        //     logger.error('socket online', userId);
        //     if (userId == null || data == null) return;
        //
        //     var index = data;
        //     var room = roomMgr.getRoomByUserId(userId);
        //     if (room != null) {
        //         var roomNo = room.roomNo;
        //         roomMgr.onlineRoom(userId, roomNo, index);//退出房间
        //         socket.to(roomNo).emit('game_whoOnline_notify',{userId:userId});
        //     }
        //     socket.userId = null;
        // });

        //退出房间
        socket.on('exit',function(data){
            var userId = socket.userId;
            logger.error('socket exit', userId);
            if (userId == null || data == null) return;

            var index = data;
            var room = roomMgr.getRoomByUserId(userId);
            if (room != null) {
                var roomNo = room.roomNo;
                roomMgr.exitRoom(userId, roomNo, index);//退出房间
                socket.to(roomNo).emit('game_whoExit_notify', userId);

                socket.leave(roomNo, null);
            }
            socket.userId = null;
            delete socketIDs[userId];
            socket.disconnect();
        });

        //请求解散
		socket.on('dissolveAction', function (data) {
            var userId = socket.userId;
            if (userId == null) return;
            var type = data;
            var room = roomMgr.getRoomByUserId(userId);
            io.to(room.roomNo).emit('game_dissolveAction_notify', {userId:userId, type:type});
            if (type == 0) { //请求解散
                gameMgr.dissolveRequest(userId, 1);
            } else if (type == 1) { //同意解散
                gameMgr.dissolveRequest(userId, 1);
            } else if (type == 2) { //拒绝解散
                gameMgr.dissolveRequest(userId, 2);
            }
        });

        //客户端心跳
        socket.on('chat',function(data){
            var userId = socket.userId;
            if (userId == null) return;
            var type = data;
            var room = roomMgr.getRoomByUserId(userId);
            if (room != null) {
                socket.to(room.roomNo).emit('game_chat_notify', {userId:userId, type:type});
            }
        });

        //客户端心跳
		socket.on('game_ping',function(){
            var userId = socket.userId;
            logger.debug('---------game_ping', userId);
            if (userId == null) return;

			socket.emit('game_pong', 0);
		});

        //-------------------------------------牛牛action--------------------------------------
		//抢庄
        // socket.on('toZhuang', function (data) {
         //    var userId = socket.userId;
         //    if (userId == null) return;
        //
         //    var zhuangBei = data;
         //    gameMgr.toZhuang(userId, zhuangBei);
        //
         //    var info = {
         //        userId: userId,
         //        bei: zhuangBei,
         //    };
        //
         //    var room = roomMgr.getRoomByUserId(userId);
         //    socket.to(room.roomNo).emit('game_toZhuang_notify', info);
        // });

        //下注
        // socket.on('xiazhu', function (data) {
        //     var userId = socket.userId;
        //     if (userId == null) return;
        //
        //     var zhu = data;
        //     gameMgr.xiaZhu(userId, zhu);
        //
        //     var info = {
        //         userId: userId,
        //         zhu: zhu,
        //     };
        //
        //     var room = roomMgr.getRoomByUserId(userId);
        //     socket.to(room.roomNo).emit('user_xiazhu_notify', info);
        // });

        //开牌
        // socket.on('toOpen', function (data) {
        //     var userId = socket.userId;
        //     if (userId == null) return;
        //
        //     var niuX = gameMgr.openPai(userId);
        //
        //     var info = {
        //         userId: userId,
        //         niuX: niuX,
        //     };
        //
        //     var room = roomMgr.getRoomByUserId(userId);
        //     socket.to(room.roomNo).emit('game_toOpen_notify', info);
        // });
        //-------------------------------------牛牛action--------------------------------------

        //-------------------------------------血流麻将action--------------------------------------
        //换牌
        // socket.on('huanPai',function(data){
        //     var userId = socket.userId;
        //     if (userId == null) return;
        //
        //     var pais = JSON.parse(data);
        //
        //     var info = {
        //         userId: userId,
        //         pais: pais,
        //     };
        //
        //     var room = roomMgr.getRoomByUserId(userId);
        //     socket.to(room.roomNo).emit('game_whoHuanpai_notify', info);
        // });
        //-------------------------------------血流麻将action--------------------------------------

        //-------------------------------------麻将action--------------------------------------
        //出牌
        socket.on('chuPai',function(data){
            var userId = socket.userId;
            if (userId == null) return;

            var pai = data;
            gameMgr.chuPai(userId, pai);
        });

        //吃
        socket.on('chi',function(data){
            var userId = socket.userId;
            if (userId == null) return;

            var type = data;
            gameMgr.chi(userId, type);
        });

        //碰
        socket.on('peng',function(data){
            var userId = socket.userId;
            if (userId == null) return;

            gameMgr.peng(userId);
        });

        //杠
        socket.on('gang',function(data){
            var userId = socket.userId;
            if (userId == null) return;

            var pai = parseInt(data);
            gameMgr.gang(userId, pai);
        });

        //胡
        socket.on('hu',function(data){
            var userId = socket.userId;
            if (userId == null) return;

            var pai = data;
            gameMgr.hu(userId, pai);
        });

        //过  遇上胡，碰，杠的时候，可以选择过
        socket.on('guo',function(data){
            var userId = socket.userId;
            if (userId == null) return;

            gameMgr.guo(userId);
        });
        //-------------------------------------麻将action--------------------------------------
	});
};

//io.in(room) == io.to(room)
//io.in(room).emit() 通知nsp下单个room里的所有客户端
//io.emit 通知nsp下的所有客户端

//server.sockets 默认的nsp

//socket.in(room) == socket.to(room)
//socket.in(room).emit() 通知nsp下单个room里的所有客户端 除了自己
//socket.broadcast.emit 通知nsp下的所有客户端 除了自己

//io.use(func) 中间件

//-------------------------------------牛牛action--------------------------------------
//通知手牌
// exports.notify_holds = function (game) { //单个通知
//     for (var i = 0; i < game.plays; i++) {
//         var seat = game.gameSeats[i];
//         var socketID = socketIDs[seat.userId];
//         var socket = io.sockets.connected[socketID];
//         socket.emit('game_holds_notify', seat.holds);
//     }
// };

//通知庄家
// exports.notify_zhuang = function (game) { //全局通知
//     var info = {
//         userId: game.zhuang,
//         bei: game.zhuangBei,
//     };
//     io.to(game.room.roomNo).emit("game_whoZhuang_notify", info);
// };

//通知补手牌
// exports.notify_holds_more = function (game) { //单个通知
//     for (var i = 0; i < game.plays; i++) {
//         var seat = game.gameSeats[i];
//         var socketID = socketIDs[seat.userId];
//         var socket = io.sockets.connected[socketID];
//         socket.emit('game_holds_more_notify', seat.holdsMore);
//     }
// };

//通知牛X
// exports.notify_niu = function (seat) { //单个通知
//     var game = seat.game;
//     var info = {
//         userId: seat.userId,
//         niuX: seat.niuX,
//     };
//     io.to(game.room.roomNo).emit("game_niux_notify", info);
// };
//-------------------------------------牛牛action--------------------------------------

//-------------------------------------麻将action--------------------------------------
exports.notify_user_majongs = function (game) {
    var seats = game.gameSeats;
    for (var i = 0; i < game.plays; i++) {
        var seat = seats[i];
        var socketID = socketIDs[seat.userId];
        var socket = io.sockets.connected[socketID];
        socket.emit('notify_user_majongs', seat.holds);
    }
};

exports.notify_user_tingpais = function (seat) {
    var socketID = socketIDs[seat.userId];
    var socket = io.sockets.connected[socketID];
    socket.emit('notify_user_tingpais', seat.tingMap);
};

exports.notify_user_operate_available = function (seat, info) {
    var socketID = socketIDs[seat.userId];
    var socket = io.sockets.connected[socketID];
    socket.emit('notify_user_operate', info);
};

exports.notify_user_mopai = function (seat, pai) {
    var game = seat.game;
    var seats = game.gameSeats;

    var obj = {turn:seat.seatIndex,};
    for (var i = 0; i < game.plays; i++) {
        var tempSeat = seats[i];
        var socketID = socketIDs[tempSeat.userId];
        var socket = io.sockets.connected[socketID];
        if (tempSeat.userId == seat.userId) { //通知自己
            var temp = {
                turn:seat.seatIndex,
                pai:pai
            };
            socket.emit('notify_user_mopai', temp);
        } else {
            socket.emit('notify_user_mopai', obj);
        }
    }
};

exports.notify_all_chupai = function (game, type) {
    var seats = game.gameSeats;

    var info = {
        pai: game.chuPai,
        type: type
    };
    for (var i = 0; i < game.plays; i++) {
        var tempSeat = seats[i];
        //不用通知摸牌方
        if (i == game.turn) continue;

        var socketID = socketIDs[tempSeat.userId];
        var socket = io.sockets.connected[socketID];
        socket.emit('notify_all_chupai', info);
    }
};

exports.notify_all_user_operate = function (seat, type, pai, chiType) {
    var game = seat.game;
    var obj = {
        turn:seat.seatIndex,
        target:game.turn,
        type:type,
        pai:pai,
    };
    if (chiType) {
        obj.chiType = chiType;
    }
    io.to(game.room.roomNo).emit("notify_all_user_operate", obj);
};
//-------------------------------------麻将action--------------------------------------

//-------------------------------------游戏action--------------------------------------
//通知游戏结束
exports.notify_game_ready = function (game) {
    io.to(game.room.roomNo).emit("game_ready_notify", game.room.statistics);
};

//通知解散结果
exports.notify_dissolve_result = function (game, result) { //全局通知
    io.to(game.room.roomNo).emit("game_dissolveResult_notify", result);
};

//通知当局牌结束 和 结果信息
exports.notify_game_result = function (game, resultInfo) { //全局通知
    io.to(game.room.roomNo).emit("game_result_notify", resultInfo);
};

//通知游戏结束 和 积分信息
exports.notify_game_end_statistics = function (game) {
    io.to(game.room.roomNo).emit("game_end_statistics_notify", game.room.statistics);
};

exports.knockout_all = function (game) {
    var room = game.room;
    for (var i = 0; i < room.users; i++) {
        var userId = room.users[i];
        var socketID = socketIDs[userId];
        var socket = io.sockets.connected[socketID];

        socket.leave(room.roomNo, null);
        socket.userId = null;
        delete socketIDs[userId];

        socket.disconnect();
    }
};
//-------------------------------------游戏action--------------------------------------